"""
Case Type   : GUC_ErrorLog
Case Name   : 修改参数log_line_prefix的值为%a，检查日志信息的前缀只有应用程序名称
Create At   : 2022/06/07
Owner       : liu-tong-8848
Description :
    1.修改参数值
    2.连接数据库执行报错的sql语句后，查看日志信息
    3.恢复参数
    4.清理残留日志
Expect      :
    1.修改参数值成功
    2.日志中记录了sql语句，日志信息前缀仅包含：应用程序名gsql
    3.恢复成功
    4.清理成功
History     :
    modified：2025-2-5 by liu-tong-8848;修改匹配条件，日志中存在相关的sql错误信息即可，不强制要求是最后几行
"""
import os
import re
import unittest
from yat.test import Node
from yat.test import macro
from testcase.utils.Common import Common
from testcase.utils.CommonSH import CommonSH
from testcase.utils.Logger import Logger
from testcase.utils.Constant import Constant


class ErrorLog(unittest.TestCase):
    def setUp(self):
        self.logger = Logger()
        self.logger.info(f"-----{os.path.basename(__file__)} start-----")
        self.primary_node = Node('PrimaryDbUser')
        self.primary_sh = CommonSH('PrimaryDbUser')
        self.primary_root = Node('PrimaryRoot')
        self.common = Common()
        self.constant = Constant()
        self.table_name = 't_guc_errorlog_case0125'
        self.dir_new = os.path.join(macro.PG_LOG_PATH, 'pg_errorlog_case0125')
        self.log_dir = 'log_directory'
        self.log_dir_default = self.common.show_param(self.log_dir)
        self.log_statement = 'log_statement'
        self.log_stat_default = self.common.show_param(self.log_statement)
        self.log_line_prefix = 'log_line_prefix'
        self.prefix_default = self.common.show_param(self.log_line_prefix)

    def test_error_log(self):
        text = "-----step1:修改参数值：log_directory设置新的路径，" \
               "log_statement = mod, log_line_prefix='%a';expect:修改参数值成功-----"
        self.logger.info(text)
        if self.dir_new != self.log_dir_default:
            result = self.primary_sh.execute_gsguc(
                'reload', self.constant.GSGUC_SUCCESS_MSG,
                f'{self.log_dir}=\'{self.dir_new}\'')
            self.assertTrue(result, '执行失败' + text)
        show_msg = self.common.show_param(self.log_dir)
        self.assertEquals(show_msg, self.dir_new, '执行失败' + text)

        self.logger.info(text)
        if 'mod' != self.log_stat_default:
            result = self.primary_sh.execute_gsguc(
                'reload', self.constant.GSGUC_SUCCESS_MSG,
                f'{self.log_statement}=mod')
            self.assertTrue(result, '执行失败' + text)
        show_msg = self.common.show_param(self.log_statement)
        self.assertEquals(show_msg, 'mod', '执行失败' + text)

        if '%a' != self.prefix_default:
            result = self.primary_sh.execute_gsguc(
                'reload', self.constant.GSGUC_SUCCESS_MSG,
                f'{self.log_line_prefix}=\'%a\'')
            self.assertTrue(result, '执行失败' + text)
        show_msg = self.common.show_param(self.log_line_prefix)
        self.assertEquals(show_msg, '%a', '执行失败' + text)

        text = '-----step2:连接数据库执行报错的sql语句后，查看日志信息;' \
               'expect:日志中记录了sql语句，日志信息前缀仅包含：应用程序名gsql-----'
        self.logger.info(text)
        sql_cmd = f"drop table if exists {self.table_name};" \
            f"create table {self.table_name}" \
            f"(id int primary key,name varchar(15));" \
            f"insert into {self.table_name} values(1,'开发'),(1,'测试');"
        self.logger.info(sql_cmd)
        sql_msg = self.primary_sh.execut_db_sql(sql_cmd)
        self.logger.info(sql_msg)
        self.assertIn(self.constant.TABLE_DROP_SUCCESS and
                      self.constant.TABLE_CREATE_SUCCESS,
                      sql_msg, '执行失败:' + text)
        self.assertIn('ERROR:  duplicate key value violates unique constraint',
                      sql_msg, '执行失败:' + text)
        self.logger.info('-------查看日志文件内容-------')
        shell_cmd = f'''ls -t {self.dir_new} '''
        self.logger.info(shell_cmd)
        logfile = os.path.join(self.dir_new,
                               self.primary_root.sh(shell_cmd).result())
        self.logger.info(logfile)
        tail_cmd = f"tail -n 40 {logfile} "
        self.logger.info(tail_cmd)
        tail_msg = self.primary_node.sh(tail_cmd).result()
        self.logger.info(tail_msg)
        self.assertIn(f"gsql 0 [BACKEND] LOG:  statement: drop table if exists "
                      f"{self.table_name};" and
                      f"gsql 0 [BACKEND] LOG:  statement: create table "
                      f"{self.table_name}(id int primary key,name varchar(15));"
                      and f"gsql 0 [BACKEND] LOG:  statement: insert into "
                      f"{self.table_name} values(1,'开发'),(1,'测试');",
                      tail_msg, '执行失败:' + text)
        self.assertIn('gsql' and
                      '[BACKEND] ERROR:  duplicate key value violates',
                      tail_msg, '执行失败:' + text)
        self.assertIn('gsql' and
                      '[BACKEND] DETAIL:  Key (id)=(1) already exists',
                      tail_msg, '执行失败:' + text)
        self.assertIn('gsql' and
                      f"[BACKEND] STATEMENT:  insert into {self.table_name} "
                      f"values(1,'开发'),(1,'测试');",
                      tail_msg, '执行失败:' + text)

    def tearDown(self):
        text = '-----step3:恢复参数;expect:恢复成功-----'
        self.logger.info(text)
        drop_cmd = f"drop table {self.table_name};"
        self.logger.info(drop_cmd)
        drop_msg = self.primary_sh.execut_db_sql(drop_cmd)
        self.logger.info(drop_msg)

        log_dir_current = self.common.show_param(self.log_dir)
        if log_dir_current != self.log_dir_default:
            self.primary_sh.execute_gsguc(
                'reload', self.constant.GSGUC_SUCCESS_MSG,
                f'{self.log_dir}=\'{self.log_dir_default}\'')
        show_log_dir = self.common.show_param(self.log_dir)

        log_stat_current = self.common.show_param(self.log_statement)
        if log_stat_current != self.log_stat_default:
            self.primary_sh.execute_gsguc(
                'reload', self.constant.GSGUC_SUCCESS_MSG,
                f'{self.log_statement}={self.log_stat_default}')
        show_log_statement = self.common.show_param(self.log_statement)

        prefix_current = self.common.show_param(self.log_line_prefix)
        if prefix_current != self.prefix_default:
            self.primary_sh.execute_gsguc(
                'reload', self.constant.GSGUC_SUCCESS_MSG,
                f'{self.log_line_prefix}=\'{self.prefix_default}\'')
        show_prefix = self.common.show_param(self.log_line_prefix)

        text_remove = '-----step4:清理残留日志文件;expect:清理成功-----'
        remove_cmd = f"rm -rf {self.dir_new}"
        remove_result = self.primary_node.sh(remove_cmd).result()
        self.logger.info(remove_result)
        remove_test_cmd = f"ls {self.dir_new}"
        remove_test_log = self.primary_node.sh(remove_test_cmd).result()
        self.logger.info(remove_test_log)

        self.logger.info('-----断言tearDown-----')
        self.assertIn(self.constant.TABLE_DROP_SUCCESS,
                      drop_msg, '执行失败:' + text)
        self.assertEquals(show_log_dir, self.log_dir_default, '执行失败' + text)
        self.assertEquals(show_log_statement, self.log_stat_default,
                          '执行失败' + text)
        self.assertEquals(show_prefix, self.prefix_default, '执行失败' + text)
        self.assertIn("No such file or directory", remove_test_log, '执行失败:' + text_remove)
        self.logger.info(f"-----{os.path.basename(__file__)} end-----")
